﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.ServiceModel;
using System.Threading;
using System.Xml.Linq;
using Zen4SyncOrchestratorServices;
using Zen4SyncPOCO.ClientTestSessionDescriptorHandler;
using Zen4SyncPOCO.POCO.Admin;
using Zen4SyncTestServerServices;

namespace Zen4SyncTestServer
{
    public class TestServerServices : ITestServerServices
    {
        private DebugLogger.DebugLogger logger;

        private bool debugLogEnabled;

        private ChannelFactory<IOrchestratorServices> orchestratorClient;

        public void StartClientSessions(List<ClientSession> clientSessionsPOCO, TestServer me)
        {
            string cfgEnableDebugLog = ConfigurationManager.AppSettings["TestServerEnableDebugLog"];
            string cfgLogFilePath = ConfigurationManager.AppSettings["TestServerDebugLogFilePath"];

            if (!String.IsNullOrEmpty(cfgEnableDebugLog) && !String.IsNullOrEmpty(cfgLogFilePath))
            {
                debugLogEnabled = Boolean.Parse(cfgEnableDebugLog);
            }
            else
            {
                debugLogEnabled = false;
            }

            if (debugLogEnabled)
            {
                logger = new DebugLogger.DebugLogger(cfgLogFilePath);
                logger.Open();
            }


            try
            {

                orchestratorClient = new ChannelFactory<IOrchestratorServices>(ConfigurationManager.AppSettings["TestServerActiveOrchestratorEndpointName"]);

                if (!Directory.Exists(me.testServer_configFilesDirectory))
                {
                    Directory.CreateDirectory(me.testServer_configFilesDirectory);
                }

                if (debugLogEnabled) logger.LogMessage(String.Format("Generating {0} ClientTestSessionDescriptors into {1}", clientSessionsPOCO.Count, me.testServer_configFilesDirectory));

                foreach (ClientSession clientSession in clientSessionsPOCO)
                {
                    // Build ClientTestSessionDescriptor
                    IClientTestSessionDescriptorHandler ctsdHandler = ClientTestSessionDescriptorHandlerFactory.Instance;
                    XElement ctsd = null;
                    try
                    {
                        ctsd = ctsdHandler.CreateClientTestSessionDescriptor(clientSession);
                    }
                    catch (Exception exc)
                    {
                        orchestratorClient.Call(services => services.ClientSessionUnableToStart(
                                  clientSession.clientSession_id
                                , String.Format(
                                    "Unable to create ClientTestSessionDescriptor XML file.\nMessage: {0}\nStack Trace:\n{1}\nInner Exception:{2}",
                                    exc.Message,
                                    exc.StackTrace,
                                    (exc.InnerException != null ? exc.InnerException.Message : "null"))));

                        continue;
                    }

                    // Save ClientTestSessionDescriptor on disk so that it can be given as input to the Zen4SyncClient                    
                    string ctsdFileName = Path.Combine(me.testServer_configFilesDirectory, String.Format("{0}.xml", clientSession.clientSession_id.ToString()));
                    ctsd.Save(ctsdFileName);
                    if (debugLogEnabled) logger.LogMessage(String.Format("Saved file {0} in {1}", ctsdFileName, me.testServer_configFilesDirectory));

                    // Start Zen4SyncClient with the ClientTestSessionDescriptor as parameter
                    if (debugLogEnabled) logger.LogMessage(String.Format("Starting Zen4SyncClient from {0}", me.testServer_loadSyncApplicationPath));
                    Thread z4sClientThread = new Thread(new ParameterizedThreadStart(StartZen4SyncClientInNewProcess));
                    z4sClientThread.Start(new string[] { "\"" + me.testServer_loadSyncApplicationPath + "\"", "\"" + ctsdFileName + "\"" });
                }
            }
            catch (Exception exc)
            {
                if (debugLogEnabled) logger.LogError(String.Format("ERROR : {0}\n{1}", exc.Message, exc.StackTrace));
                else throw exc;
            }
            finally
            {
                if (debugLogEnabled && logger.IsOpened) logger.Close();
            }

            return;
        }

        /// <summary>
        /// Starts a Zen4SyncClient in a new process.
        /// </summary>
        /// <param name="args">
        /// A string array containing :
        ///  [0] : The path to the Zen4SyncClient binary.
        ///  [1] : The path to the ClientTestSessionDescriptor file that will be used by the Zen4SyncClient.
        /// </param>
        private void StartZen4SyncClientInNewProcess(object args)
        {
            string[] stringArgs = (string[])args;

            ProcessStartInfo processStartInfo = new ProcessStartInfo(stringArgs[0], stringArgs[1]);
            Process.Start(processStartInfo);
        }
    }
}
